#pragma once

#include <iostream>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cerrno>
#include <signal.h>
#include <stdlib.h>
#include <cstring>
#include <unistd.h>
#include <cassert>
#include <pthread.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string>
#include <sys/epoll.h>
#include <fcntl.h>

#define BUFFER_NUM 1024
#define MAX_EVENTS 1024

// 会直接退出
void myAssert(bool condition, const char *errmsg)
{
    if (!condition)
    {
        perror(errmsg);
        exit(EXIT_FAILURE);
    }
}

// 设置非阻塞模式
void setnonblocking(int fd)
{
    int flag = fcntl(fd, F_GETFL, 0);
    flag |= O_NONBLOCK;
    fcntl(fd, F_SETFL, flag);
}

class Socket
{
public:
    Socket(std::string ip = "", uint16_t port = 8080)
        : _ip(ip), _port(port)
    {
        int _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        myAssert(_sockfd != -1, "sock error");
    }

    int GetFd(){ return _sockfd;}

    void Bind()
    {
        struct sockaddr_in serv_addr;
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = _ip == "" ? INADDR_ANY : inet_addr(_ip.c_str());
        serv_addr.sin_port = _port;
        myAssert(bind(_sockfd, (sockaddr *)&serv_addr, sizeof(serv_addr)) != -1, "bind error");
    }

    void Listen()
    {
        myAssert(listen(_sockfd, SOMAXCONN) != -1, "listen error");
    }

    int Accept()
    {
        struct sockaddr_in cli_addr;
        socklen_t len = sizeof(cli_addr);
        int cli_fd = accept(_sockfd, (sockaddr *)&cli_addr, &len);
        myAssert(cli_fd != -1, "accept error");
        return cli_fd;
    }

    ~Socket()
    {
        close(_sockfd);
    }

private:
    int _sockfd;
    std::string _ip;
    uint16_t _port;
};

class Epoll
{
public:
    Epoll() 
    {
        _epfd=epoll_create1(0);
        bzero(events,sizeof(events));
    }
    void addFd(int fd, int flag)
    {
        bzero(&ev,sizeof(ev));
        ev.data.fd=fd;
        ev.events=flag;
        epoll_ctl(_epfd,EPOLL_CTL_ADD,fd,&ev);
    } 
    int size()
    {
        return epoll_wait(_epfd,events,MAX_EVENTS,-1);
    }
private : 
    int _epfd;
    struct epoll_event events[MAX_EVENTS];
    struct epoll_event ev;
};
